<?php

namespace app\company\controller;

use app\common\controller\CompanyController;
use app\common\enum\order\OrderStatus;
use app\common\enum\order\OrderType;
use app\common\enum\order\PickStatus;
use app\common\enum\purchase\OrderStatus as PurchaseStatus;
use app\common\enum\purchase\OrderType as PurchaseOrderType;
use app\common\exception\BaseException;
use app\common\model\DealerGoodsSpec;
use app\common\model\DealerGoods;
use app\common\service\annotation\ControllerAnnotation;
use app\common\service\annotation\NodeAnnotation;
use app\company\model\CompanyOrder;
use app\company\model\CompanyOrderDetail;
use app\company\model\CompanyPickOrder;
use app\company\model\CompanyPickOrderDetail;
use app\company\model\DealerOrder;
use app\company\model\DealerOrderDetail;
use app\Request;
use think\App;
use think\Paginator;
use think\response\Json;

/**
 * @ControllerAnnotation(title="出库单")
 */
class OutOrder extends CompanyController
{
    private mixed $typeArr = [
        'XS' => 1, // 销售出库单
        'CT' => 2, // 采退出库单
    ];
    /**
     * @var array|int|mixed
     */
    private mixed $type;

    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->model = new CompanyOrder();
        $this->joinTable = 'detail,goods';
        $this->each = true;
        $this->type = $app->request->param('type') ?? 0;
    }

    /**
     * @NodeAnnotation(title="订单列表")
     */
    public function list(): Json
    {
        list($limit, $where) = $this->buildSearchParams();
        if (!in_array($this->type, $this->typeArr)) $where[] = ['id', '<', 0];
        if ($this->type == $this->typeArr['XS']) {
            $list = $this->xsList($limit, $where);
        } else {
            $list = $this->ctList($limit, $where);
        }
        return $this->success($list);
    }

    private function xsList($limit, $where): array
    {
        $sql = $this->model->with([
            'detail' => function ($query) {
                $query->with([
                    'goods' => function ($query) {
                        $query->field('id,image,name')->withTrashed();
                    },
                    'goodsSpec' => function ($query) {
                        $query->field('id,image,name,unit,sale_price')->withTrashed();
                    }
                ]);
            },
            'store' => function ($query) {
                $query->field('id,name,contact,phone,address');
            },
            'dealer' => function ($query) {
                $query->field('id,name,tc_rate,tp_rate,tx_rate');
            },
            'salesman' => function ($query) {
                $query->field('id,rename');
            }
        ])->where('order_type', OrderType::SALES)
            ->where($where)
            ->where('order_status', '<>', OrderStatus::CANCEL)
            ->where('check_status', '=', 2)
            ->where('is_cx',1)
            ->where($this->defaultWhere)->order($this->sort);
        $list = $sql->paginate($limit ?? 10)->toArray();

        $list['data'] =  $this->fordata($list['data']);
       
        $all_data = $sql->select()->toArray();
        $all_data =  $this->fordata($all_data);
        $list['tc_rate_total_money'] = sprintf("%.2f",array_sum(array_column($all_data, 'tc_rate_money')));
        $list['tp_rate_total_money'] = sprintf("%.2f",array_sum(array_column($all_data, 'tp_rate_money')));
        $list['tx_rate_total_money'] = sprintf("%.2f",array_sum(array_column($all_data, 'tx_rate_money')));
        // 服务费用合计
        $list['rate_total_money'] = sprintf("%.2f",array_sum(array_column($all_data, 'money')));
        // 订单金额合计
        $list['order_total_money'] = sprintf("%.2f",array_sum(array_column($all_data, 'order_amount')));
        // 出库金额合计
        $list['out_total_money'] = sprintf("%.2f",array_sum(array_column($all_data, 'out_money')));
        return $list;
    }

    public function fordata($data){
        foreach ($data as $k => &$vo) {
            // 根据 dealer_goods_id 分组
            $grouped = array_reduce($vo['detail'], function ($result, $item) {
                $id = $item['dealer_goods_id'];
                if (!isset($result[$id])) {
                    $result[$id] = [];
                }
                $result[$id][] = $item;
                return $result;
            }, []);
           
            // 获取商品种类数量
            $goodsTypeCount = array_map(function ($group) {
                return count(array_unique(array_column($group, 'goods_type')));
            }, $grouped);

            // 计算总的商品种类数量
            $vo['goods_cate_num'] = array_sum($goodsTypeCount);
            $outMoney = $financeMoney = 0;
            $detail = $vo['detail'];

            array_walk($detail, function ($v) use (&$outMoney, &$financeMoney) {
//                        $outMoney += $v['num'] * $v['goodsSpec']['sale_price'];
                $outMoney = $v['goods_type'] == 1 && $v['true_price'] > 0 ? $v['total_price'] : bcadd($outMoney, bcmul($v['num'], $v['goodsSpec']['sale_price'], 2), 2);
                $money = $v['sale_price'];
                if ($v['goods_type'] == 1 && $v['true_price'] >0 ) $money = $v['true_price'];
                $financeMoney = bcadd($financeMoney, bcmul($v['num'], $money, 2), 2);
            });
            $vo['out_money'] = $outMoney;
            $vo['finance_money'] = $financeMoney;
            $vo['dealer']['out_money'] = $vo['out_money'];
            $tc_rate_money = floatval($outMoney) * floatval($vo['dealer']['tc_rate'])/100;
            $tp_rate_money = $vo['is_self_order']== 1 ? floatval($outMoney) * floatval($vo['dealer']['tp_rate'])/100 : 0;
            $tx_rate_money = $vo['is_self_order']== 1 ? floatval($outMoney) * floatval($vo['dealer']['tx_rate'])/100 : 0;
            $vo['dealer']['tc_rate_money'] = sprintf("%.2f",$tc_rate_money);
            $vo['dealer']['tp_rate_money'] = sprintf("%.2f",$tp_rate_money);
            $vo['dealer']['tx_rate_money'] = sprintf("%.2f",$tx_rate_money);
            $vo[$k]['dealer']['finance_money'] = floatval($financeMoney);
            $vo['dealer']['money'] = sprintf("%.2f",($tc_rate_money +  $tp_rate_money +  $tx_rate_money)) ;
            //rate money
            $vo['tc_rate_money'] = $tc_rate_money;
            $vo['tp_rate_money'] = $tp_rate_money;
            $vo['tx_rate_money'] = $tx_rate_money;
            $vo['money'] =$tc_rate_money +  $tp_rate_money +  $tx_rate_money ;

        }
        return $data;
    }
    private function ctList($limit, $where): Paginator
    {
        $where[] = ['order_type', '=', PurchaseOrderType::CT];
        $where[] = ['order_status', 'in', [PurchaseStatus::PASS, PurchaseStatus::PUT_IN, PurchaseStatus::FINISHED]];
        $list = (new DealerOrder())->with([
            'dealer' => function ($query) {
                $query->field('id,name');
            },
            'supplier' => function ($query) {
                $query->field('id,name');
            },
            'warehouse' => function ($query) {
                $query->field('id,name');
            },
            'detail' => function ($query) {
                $query->with([
                    'goods' => function ($query) {
                        $query->field('id,image,name,cate_id');
                    },
                    'spec' => function ($query) {
                        $query->field('id,image,name,unit,ratio');
                    },
                ]);
            },
        ])->where($where)->where($this->defaultWhere)->order($this->sort)->paginate($limit)->each(function ($item) {
            $detail = $item->detail->toArray();
            // 获取商品种类数量
            $cateIds = [];
            array_walk($detail, function ($v) use (&$cateIds) {
                $dealer_cate_id = (new DealerGoods())->where('id', $v['dealer_goods_id'])->withTrashed()->value('cate_id');
                if ($dealer_cate_id) $cateIds[] = $dealer_cate_id;
            });
            $item->goods_cate_num = count(array_unique($cateIds));
            // 2024.12.06增加返回生成拣货单按钮判断字段
            $pickDetail = (new CompanyPickOrderDetail())->where('dealer_order_id', $item->id)->find();
            $item->pick_status = $pickDetail ? 2 : 1;
            // 统仓费

        });
        return $list;
    }

    /**
     * @NodeAnnotation(title="生成拣货单")
     * @param Request $request
     * @return Json
     */
    public function pick(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        $id = $request->post('id', '');
        if (empty($id)) return $this->error('订单ID不能为空');
        $id = explode(',', $id);
        if (empty($post['type']) || !in_array($post['type'], $this->typeArr)) return $this->error('当前请求参数非法！');
        if ($post['type'] == $this->typeArr['CT']) {
            $pk = 'dealer_order_id';
            $model = new DealerOrder();
            $detailModel = new DealerOrderDetail();
        } else {
            $pk = 'company_order_id';
            $model = $this->model;
            $detailModel = new CompanyOrderDetail();
        }
        try {
            $this->model->transaction(function () use ($id, $pk, $model, $detailModel, $post) {
                $pickModel = new CompanyPickOrder();
                $pickDetailModel = new CompanyPickOrderDetail();
                // 判断是否已经存在捡货单
                array_walk($id, function ($v) use ($pk, $model, $pickDetailModel,$post) {
                    //查询捡货详情
                    $pickOrderDetail = $pickDetailModel->where($pk, $v)->find();
                    if ($pickOrderDetail) {
                        $orderNo = $model->where('id', $v)->value('order_no');
                        throw new BaseException(['message' => '订单【' . $orderNo . '】已存在拣货单中']);
                    }
                    if ($post['type'] == $this->typeArr['XS']) {
                        $orderInfo = $model->find($v);
                        if($orderInfo->order_status == OrderStatus::FINISH)throw new BaseException(['message' => '订单【' . $orderInfo->order_no . '】已配送完成，无法生成拣货单']);
                    }
                });
                $where = [];
                if ($post['type'] == $this->typeArr['CT']) {
                    $where[] = ['order_status','=',\app\common\enum\purchase\OrderStatus::PASS];
                } else {
                    $where[] = ['order_status','=',OrderStatus::BEING];
                    $where[] = ['check_status','=',2];
                }
                // 过滤订单
                $orderIds = $model->where('id', 'in', $id)
//                    ->where('order_status', OrderStatus::PASS)
                    ->where($where)
                    ->column('id');
//                if (empty($orderIds)) throw new BaseException(['message' => '订单状态不正确,无法拣货']);
                // 生成分拣单
                if ($post['type'] == $this->typeArr['CT']) {
                    $pick_num = $detailModel->whereIn($pk, $orderIds)->sum('num');
                    $true_pick_num = $detailModel->whereIn($pk, $orderIds)->sum('real_num');
                } else {
                    $true_pick_num = $pick_num = $detailModel->whereIn($pk, $orderIds)->sum('num');
                }
                $pickModel->save([
                    'company_id' => $this->companyId,
                    'type' => $post['type'],
                    'pick_order_no' => generateOrderNo('PK'),
                    $pk . 's' => implode(',', $orderIds),
                    'order_num' => count($orderIds),
                    'pick_num' => $pick_num,
                    'true_pick_num' => $true_pick_num
                ]);
                // 生成分拣单详情表
                $detail = array_map(function ($orderId) use ($pickModel, $pk, $model) {
                    $dealerId = $model->where('id', $orderId)->value('dealer_id');
                    return [
                        'company_pick_order_id' => $pickModel->id,
                        $pk => $orderId,
                        'dealer_id' => $dealerId,
                    ];
                }, $orderIds);
                $pickModel->detail()->saveAll($detail);

                // 修改单据状态
                if ($post['type'] == $this->typeArr['CT']) {
                    $model->where('id', 'in', $id)->save(['order_status' => PurchaseStatus::PUT_IN]);
                    // 扣库存
                    $dealerGoodsSpec = new DealerGoodsSpec();
                    $goodsDetail = $detailModel->field('id,dealer_goods_spec_id,real_num')->whereIn($pk, $orderIds)->select();
                    foreach ($goodsDetail as $v) {
                        $dealerGoodsSpec->where('id', $v['dealer_goods_spec_id'])
                            ->dec('stock', $v['real_num'])->save();
                    }
                }
                $this->model->whereIn('id', $orderIds)->save(['pick_status' => PickStatus::PICKED]);
//                else{
//                    $model->save(['order_status' => OrderStatus::FINISH]);
//                }
            });
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }
        return $this->success('拣货成功');
    }
}